home *** CD-ROM | disk | FTP | other *** search
- ; -----------------------------------------------------------------------
- ;
- ; Copyright 2003-2004 H. Peter Anvin - All Rights Reserved
- ;
- ; Permission is hereby granted, free of charge, to any person
- ; obtaining a copy of this software and associated documentation
- ; files (the "Software"), to deal in the Software without
- ; restriction, including without limitation the rights to use,
- ; copy, modify, merge, publish, distribute, sublicense, and/or
- ; sell copies of the Software, and to permit persons to whom
- ; the Software is furnished to do so, subject to the following
- ; conditions:
- ;
- ; The above copyright notice and this permission notice shall
- ; be included in all copies or substantial portions of the Software.
- ;
- ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- ; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- ; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- ; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- ; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- ; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- ; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- ; OTHER DEALINGS IN THE SOFTWARE.
- ;
- ; -----------------------------------------------------------------------
-
- ;
- ; mbr.asm
- ;
- ; Simple Master Boot Record, including support for EBIOS extensions.
- ;
- ; The MBR lives in front of the boot sector, and is responsible for
- ; loading the boot sector of the active partition. The EBIOS support
- ; is needed if the active partition starts beyond cylinder 1024.
- ;
- ; This MBR determines all geometry info at runtime. It uses only the
- ; linear block field in the partition table. It does, however, pass
- ; the partition table information unchanged to the target OS.
- ;
- ; This MBR should be "8086-clean", i.e. not require a 386.
- ;
-
- %include "bios.inc"
-
- ;
- ; Note: The MBR is actually loaded at 0:7C00h, but we quickly move it down to
- ; 0600h.
- ;
- section .text
- cpu 8086
- org 0600h
-
- _start: cli
- xor ax,ax
- mov ds,ax
- mov es,ax
- mov ss,ax
- mov sp,7C00h
- sti
- cld
- mov si,sp ; Start address
- mov di,0600h ; Destination address
- mov cx,512/2
- rep movsw
-
- ;
- ; Now, jump to the copy at 0600h so we can load the boot sector at 7C00h.
- ; Since some BIOSes seem to think 0000:7C00h and 07C0:0000h are the same
- ; thing, use a far jump to canonicalize the address. This also makes
- ; sure that it is a code speculation barrier.
- ;
-
- jmp 0:next ; Jump to copy at 0600h
-
- next:
- mov [DriveNo], dl ; Drive number stored in DL
- ;
- ; Check for CHS parameters. This doesn't work on floppy disks,
- ; but for an MBR we don't care.
- ;
- mov ah,08h ; Get drive parameters
- int 13h
- xor ax,ax
- mov al,dh
- inc ax ; From 0-based to count
- mov [Heads],ax
- and cl,3Fh ; Max sector number
- mov [Sectors],cl
- ; Note: we actually don't care about the number of
- ; cylinders, since that's the highest-order division
-
- ;
- ; Now look for one (and only one) active partition.
- ;
- mov si,PartitionTable
- xor ax,ax
- mov cx,4
- checkpartloop:
- test byte [si],80h
- jz .notactive
- inc ax
- mov di,si
- .notactive: add si,byte 16
- loop checkpartloop
-
- cmp ax,byte 1 ; Better be only one
- jnz not_one_partition
-
- ;
- ; Now we have the active partition partition information in DS:DI.
- ; Check to see if we support EBIOS.
- ;
- mov dl,[DriveNo]
- mov ax,4100h
- mov bx,055AAh
- xor cx,cx
- xor dh,dh
- stc
- int 13h
- jc no_ebios
- cmp bx,0AA55h
- jne no_ebios
- test cl,1 ; LBA device access
- jz no_ebios
- ;
- ; We have EBIOS. Load the boot sector using LBA.
- ;
- push di
- mov si,dapa
- mov bx,[di+8] ; Copy the block address
- mov [si+8],bx
- mov bx,[di+10]
- mov [si+10],bx
- mov dl,[DriveNo]
- mov ah,42h ; Extended Read
- jmp short common_tail
- ;
- ; No EBIOS. Load the boot sector using CHS.
- ;
- no_ebios:
- push di
- mov ax,[di+8]
- mov dx,[di+10]
- div word [Sectors]
- inc dx
- mov cx,dx ; Sector #
- xor dx,dx
- div word [Heads]
- ; DX = head #, AX = cylinder #
- mov ch,al
- shr ax,1
- shr ax,1
- and al,0C0h
- or cl,al
- mov dh,dl ; Head #
- mov dl,[DriveNo]
- mov bx,7C00h
- mov ax,0201h ; Read one sector
- common_tail:
- int 13h
- jc disk_error
- pop si ; DS:SI -> partition table entry
- ;
- ; Verify that we have a boot sector, jump
- ;
- cmp word [7C00h+510],0AA55h
- jne missing_os
- cli
- jmp 0:7C00h ; Jump to boot sector; far
- ; jump is speculation barrier
- ; (Probably not neecessary, but
- ; there is plenty of space.)
-
- not_one_partition:
- ja too_many_os
- missing_os:
- mov si,missing_os_msg
- jmp short die
- too_many_os:
- disk_error:
- mov si,bad_disk_msg
- die:
- .msgloop:
- lodsb
- and al,al
- jz .now
- mov ah,0Eh ; TTY output
- mov bh,[BIOS_page] ; Current page
- mov bl,07h
- int 10h
- jmp short .msgloop
- .now:
- jmp short .now
-
- align 4, db 0 ; Begin data area
-
- ;
- ; EBIOS disk address packet
- ;
- dapa:
- dw 16 ; Packet size
- .count: dw 1 ; Block count
- .off: dw 7C00h ; Offset of buffer
- .seg: dw 0 ; Segment of buffer
- .lba: dd 0 ; LBA (LSW)
- dd 0 ; LBA (MSW)
-
- ; CHS information
- Heads: dw 0
- Sectors: dw 0
-
- ; Error messages
- missing_os_msg db 'Missing operating system', 13, 10, 0
- bad_disk_msg db 'Operating system loading error', 13, 10, 0
-
- ;
- ; Maximum MBR size: 446 bytes; end-of-boot-sector signature also needed.
- ; Note that some operating systems (NT, DR-DOS) put additional stuff at
- ; the end of the MBR, so shorter is better. Location 440 is known to
- ; have a 4-byte attempt-at-unique-ID for some OSes.
- ;
-
- PartitionTable equ $$+446 ; Start of partition table
-
- ;
- ; BSS data; put at 800h
- ;
- DriveNo equ 0800h
-